home *** CD-ROM | disk | FTP | other *** search
/ Programming Windows 95 / Programming Windows 95.iso / code / CHAP11 / POPPAD.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-01-01  |  16.8 KB  |  473 lines

  1. /*---------------------------------------
  2.    POPPAD.C -- Popup Editor
  3.                (c) Charles Petzold, 1996
  4.   ---------------------------------------*/
  5.  
  6. #include <windows.h>
  7. #include <commdlg.h>
  8. #include <stdlib.h>
  9. #include "poppad.h"
  10.  
  11. #define EDITID   1
  12. #define UNTITLED "(untitled)"
  13.  
  14. LRESULT CALLBACK WndProc      (HWND, UINT, WPARAM, LPARAM) ;
  15. BOOL    CALLBACK AboutDlgProc (HWND, UINT, WPARAM, LPARAM) ;
  16.  
  17.           // Functions in POPFILE.C
  18.  
  19. void PopFileInitialize (HWND) ;
  20. BOOL PopFileOpenDlg    (HWND, PSTR, PSTR) ;
  21. BOOL PopFileSaveDlg    (HWND, PSTR, PSTR) ;
  22. BOOL PopFileRead       (HWND, PSTR) ;
  23. BOOL PopFileWrite      (HWND, PSTR) ;
  24.  
  25.           // Functions in POPFIND.C
  26.  
  27. HWND PopFindFindDlg     (HWND) ;
  28. HWND PopFindReplaceDlg  (HWND) ;
  29. BOOL PopFindFindText    (HWND, int *, LPFINDREPLACE) ;
  30. BOOL PopFindReplaceText (HWND, int *, LPFINDREPLACE) ;
  31. BOOL PopFindNextText    (HWND, int *) ;
  32. BOOL PopFindValidFind   (void) ;
  33.  
  34.           // Functions in POPFONT.C
  35.  
  36. void PopFontInitialize   (HWND) ;
  37. BOOL PopFontChooseFont   (HWND) ;
  38. void PopFontSetFont      (HWND) ;
  39. void PopFontDeinitialize (void) ;
  40.  
  41.           // Functions in POPPRNT.C
  42.  
  43. BOOL PopPrntPrintFile (HINSTANCE, HWND, HWND, PSTR) ;
  44.  
  45.           // Global variables
  46.  
  47. static char szAppName[] = "PopPad" ;
  48. static HWND hDlgModeless ;
  49.  
  50. int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
  51.                     PSTR szCmdLine, int iCmdShow)
  52.      {
  53.      MSG         msg ;
  54.      HWND        hwnd ;
  55.      HACCEL      hAccel ;
  56.      WNDCLASSEX  wndclass ;
  57.  
  58.      wndclass.cbSize        = sizeof (wndclass) ;
  59.      wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
  60.      wndclass.lpfnWndProc   = WndProc ;
  61.      wndclass.cbClsExtra    = 0 ;
  62.      wndclass.cbWndExtra    = 0 ;
  63.      wndclass.hInstance     = hInstance ;
  64.      wndclass.hIcon         = LoadIcon (hInstance, szAppName) ;
  65.      wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
  66.      wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
  67.      wndclass.lpszMenuName  = szAppName ;
  68.      wndclass.lpszClassName = szAppName ;
  69.      wndclass.hIconSm       = LoadIcon (hInstance, szAppName) ;
  70.  
  71.      RegisterClassEx (&wndclass) ;
  72.  
  73.      hwnd = CreateWindow (szAppName, NULL,
  74.                           WS_OVERLAPPEDWINDOW,
  75.                           CW_USEDEFAULT, CW_USEDEFAULT,
  76.                           CW_USEDEFAULT, CW_USEDEFAULT,
  77.                           NULL, NULL, hInstance, szCmdLine) ;
  78.  
  79.      ShowWindow (hwnd, iCmdShow) ;
  80.      UpdateWindow (hwnd) ; 
  81.  
  82.      hAccel = LoadAccelerators (hInstance, szAppName) ;
  83.  
  84.      while (GetMessage (&msg, NULL, 0, 0))
  85.           {
  86.           if (hDlgModeless == NULL || !IsDialogMessage (hDlgModeless, &msg))
  87.                {
  88.                if (!TranslateAccelerator (hwnd, hAccel, &msg))
  89.                     {
  90.                     TranslateMessage (&msg) ;
  91.                     DispatchMessage (&msg) ;
  92.                     }
  93.                }
  94.           }
  95.      return msg.wParam ;
  96.      }
  97.  
  98. void DoCaption (HWND hwnd, char *szTitleName)
  99.      {
  100.      char szCaption[64 + _MAX_FNAME + _MAX_EXT] ;
  101.  
  102.      wsprintf (szCaption, "%s - %s", szAppName,
  103.                szTitleName[0] ? szTitleName : UNTITLED) ;
  104.  
  105.      SetWindowText (hwnd, szCaption) ;
  106.      }
  107.  
  108. void OkMessage (HWND hwnd, char *szMessage, char *szTitleName)
  109.      {
  110.      char szBuffer[64 + _MAX_FNAME + _MAX_EXT] ;
  111.  
  112.      wsprintf (szBuffer, szMessage, szTitleName[0] ? szTitleName : UNTITLED) ;
  113.  
  114.      MessageBox (hwnd, szBuffer, szAppName, MB_OK | MB_ICONEXCLAMATION) ;
  115.      }
  116.  
  117. short AskAboutSave (HWND hwnd, char *szTitleName)
  118.      {
  119.      char szBuffer[64 + _MAX_FNAME + _MAX_EXT] ;
  120.      int  iReturn ;
  121.  
  122.      wsprintf (szBuffer, "Save current changes in %s?",
  123.                szTitleName[0] ? szTitleName : UNTITLED) ;
  124.  
  125.      iReturn = MessageBox (hwnd, szBuffer, szAppName,
  126.                            MB_YESNOCANCEL | MB_ICONQUESTION) ;
  127.  
  128.      if (iReturn == IDYES)
  129.           if (!SendMessage (hwnd, WM_COMMAND, IDM_SAVE, 0L))
  130.                iReturn = IDCANCEL ;
  131.  
  132.      return iReturn ;
  133.      }
  134.  
  135. LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
  136.      {
  137.      static BOOL      bNeedSave = FALSE ;
  138.      static char      szFileName[_MAX_PATH] ;
  139.      static char      szTitleName[_MAX_FNAME + _MAX_EXT] ;
  140.      static HINSTANCE hInst ;
  141.      static HWND      hwndEdit ;
  142.      static int       iOffset ;
  143.      static UINT      iMsgFindReplace ;
  144.      int              iSelBeg, iSelEnd, iEnable ;
  145.      LPFINDREPLACE    pfr ;
  146.  
  147.      switch (iMsg)
  148.           {
  149.           case WM_CREATE :
  150.                hInst = ((LPCREATESTRUCT) lParam) -> hInstance ;
  151.  
  152.                          // Create the edit control child window
  153.  
  154.                hwndEdit = CreateWindow ("edit", NULL,
  155.                          WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL |
  156.                               WS_BORDER | ES_LEFT | ES_MULTILINE |
  157.                               ES_NOHIDESEL | ES_AUTOHSCROLL | ES_AUTOVSCROLL,
  158.                          0, 0, 0, 0,
  159.                          hwnd, (HMENU) EDITID, hInst, NULL) ;
  160.  
  161.                SendMessage (hwndEdit, EM_LIMITTEXT, 32000, 0L) ;
  162.  
  163.                          // Initialize common dialog box stuff
  164.  
  165.                PopFileInitialize (hwnd) ;
  166.                PopFontInitialize (hwndEdit) ;
  167.  
  168.                iMsgFindReplace = RegisterWindowMessage (FINDMSGSTRING) ;
  169.  
  170.                          // Process command line
  171.  
  172.                lstrcpy (szFileName, (PSTR)
  173.                         (((LPCREATESTRUCT) lParam)->lpCreateParams)) ;
  174.  
  175.                if (strlen (szFileName) > 0)
  176.                     {
  177.                     GetFileTitle (szFileName, szTitleName,
  178.                                   sizeof (szTitleName)) ;
  179.  
  180.                     if (!PopFileRead (hwndEdit, szFileName))
  181.                          OkMessage (hwnd, "File %s cannot be read!",
  182.                                           szTitleName) ;
  183.                     }
  184.  
  185.                DoCaption (hwnd, szTitleName) ;
  186.                return 0 ;
  187.  
  188.           case WM_SETFOCUS :
  189.                SetFocus (hwndEdit) ;
  190.                return 0 ;
  191.  
  192.           case WM_SIZE : 
  193.                MoveWindow (hwndEdit, 0, 0, LOWORD (lParam),
  194.                                            HIWORD (lParam), TRUE) ;
  195.                return 0 ;
  196.  
  197.           case WM_INITMENUPOPUP :
  198.                switch (lParam)
  199.                     {
  200.                     case 1 :        // Edit menu
  201.  
  202.                               // Enable Undo if edit control can do it
  203.  
  204.                          EnableMenuItem ((HMENU) wParam, IDM_UNDO,
  205.                               SendMessage (hwndEdit, EM_CANUNDO, 0, 0L) ?
  206.                                    MF_ENABLED : MF_GRAYED) ;
  207.  
  208.                               // Enable Paste if text is in the clipboard
  209.  
  210.                          EnableMenuItem ((HMENU) wParam, IDM_PASTE,
  211.                               IsClipboardFormatAvailable (CF_TEXT) ?
  212.                                    MF_ENABLED : MF_GRAYED) ;
  213.  
  214.                               // Enable Cut, Copy, and Del if text is selected
  215.  
  216.                          SendMessage (hwndEdit, EM_GETSEL, (WPARAM) &iSelBeg,
  217.                                                            (LPARAM) &iSelEnd) ;
  218.  
  219.                          iEnable = iSelBeg != iSelEnd ? MF_ENABLED : MF_GRAYED ;
  220.  
  221.                          EnableMenuItem ((HMENU) wParam, IDM_CUT,   iEnable) ;
  222.                          EnableMenuItem ((HMENU) wParam, IDM_COPY,  iEnable) ;
  223.                          EnableMenuItem ((HMENU) wParam, IDM_CLEAR, iEnable) ;
  224.                          break ;
  225.  
  226.                     case 2 :        // Search menu
  227.  
  228.                               // Enable Find, Next, and Replace if modeless
  229.                               //   dialogs are not already active
  230.  
  231.                          iEnable = hDlgModeless == NULL ?
  232.                                         MF_ENABLED : MF_GRAYED ;
  233.  
  234.                          EnableMenuItem ((HMENU) wParam, IDM_FIND,    iEnable) ;
  235.                          EnableMenuItem ((HMENU) wParam, IDM_NEXT,    iEnable) ;
  236.                          EnableMenuItem ((HMENU) wParam, IDM_REPLACE, iEnable) ;
  237.                          break ;
  238.                     }
  239.                return 0 ;
  240.  
  241.           case WM_COMMAND :
  242.                               // Messages from edit control
  243.  
  244.                if (lParam && LOWORD (wParam) == EDITID)
  245.                     {
  246.                     switch (HIWORD (wParam))
  247.                          {
  248.                          case EN_UPDATE :
  249.                               bNeedSave = TRUE ;
  250.                               return 0 ;
  251.  
  252.                          case EN_ERRSPACE :
  253.                          case EN_MAXTEXT :
  254.                               MessageBox (hwnd, "Edit control out of space.",
  255.                                         szAppName, MB_OK | MB_ICONSTOP) ;
  256.                               return 0 ;
  257.                          }
  258.                     break ;
  259.                     }
  260.  
  261.                switch (LOWORD (wParam))
  262.                     {
  263.                               // Messages from File menu
  264.  
  265.                     case IDM_NEW :
  266.                          if (bNeedSave && IDCANCEL ==
  267.                                    AskAboutSave (hwnd, szTitleName))
  268.                               return 0 ;
  269.  
  270.                          SetWindowText (hwndEdit, "\0") ;
  271.                          szFileName[0]  = '\0' ;
  272.                          szTitleName[0] = '\0' ;
  273.                          DoCaption (hwnd, szTitleName) ;
  274.                          bNeedSave = FALSE ;
  275.                          return 0 ;
  276.  
  277.                     case IDM_OPEN :
  278.                          if (bNeedSave && IDCANCEL ==
  279.                                    AskAboutSave (hwnd, szTitleName))
  280.                               return 0 ;
  281.  
  282.                          if (PopFileOpenDlg (hwnd, szFileName, szTitleName))
  283.                               {
  284.                               if (!PopFileRead (hwndEdit, szFileName))
  285.                                    {
  286.                                    OkMessage (hwnd, "Could not read file %s!",
  287.                                                     szTitleName) ;
  288.                                    szFileName[0]  = '\0' ;
  289.                                    szTitleName[0] = '\0' ;
  290.                                    }
  291.                               }
  292.  
  293.                          DoCaption (hwnd, szTitleName) ;
  294.                          bNeedSave = FALSE ;
  295.                          return 0 ;
  296.  
  297.                     case IDM_SAVE :
  298.                          if (szFileName[0])
  299.                               {
  300.                               if (PopFileWrite (hwndEdit, szFileName))
  301.                                    {
  302.                                    bNeedSave = FALSE ;
  303.                                    return 1 ;
  304.                                    }
  305.                               else
  306.                                    OkMessage (hwnd, "Could not write file %s",
  307.                                                     szTitleName) ;
  308.                               return 0 ;
  309.                               }
  310.                                                   // fall through
  311.                     case IDM_SAVEAS :
  312.                          if (PopFileSaveDlg (hwnd, szFileName, szTitleName))
  313.                               {
  314.                               DoCaption (hwnd, szTitleName) ;
  315.  
  316.                               if (PopFileWrite (hwndEdit, szFileName))
  317.                                    {
  318.                                    bNeedSave = FALSE ;
  319.                                    return 1 ;
  320.                                    }
  321.                               else
  322.                                    OkMessage (hwnd, "Could not write file %s",
  323.                                                     szTitleName) ;
  324.                               }
  325.                          return 0 ;
  326.  
  327.                     case IDM_PRINT :
  328.                          if (!PopPrntPrintFile (hInst, hwnd, hwndEdit,
  329.                                                 szTitleName))
  330.                               OkMessage (hwnd, "Could not print file %s",
  331.                                          szTitleName) ;
  332.                          return 0 ;
  333.  
  334.                     case IDM_EXIT :
  335.                          SendMessage (hwnd, WM_CLOSE, 0, 0) ;
  336.                          return 0 ;
  337.  
  338.                               // Messages from Edit menu
  339.  
  340.                     case IDM_UNDO :
  341.                          SendMessage (hwndEdit, WM_UNDO, 0, 0) ;
  342.                          return 0 ;
  343.  
  344.                     case IDM_CUT :
  345.                          SendMessage (hwndEdit, WM_CUT, 0, 0) ;
  346.                          return 0 ;
  347.  
  348.                     case IDM_COPY :
  349.                          SendMessage (hwndEdit, WM_COPY, 0, 0) ;
  350.                          return 0 ;
  351.  
  352.                     case IDM_PASTE :
  353.                          SendMessage (hwndEdit, WM_PASTE, 0, 0) ;
  354.                          return 0 ;
  355.  
  356.                     case IDM_CLEAR :
  357.                          SendMessage (hwndEdit, WM_CLEAR, 0, 0) ;
  358.                          return 0 ;
  359.  
  360.                     case IDM_SELALL :
  361.                          SendMessage (hwndEdit, EM_SETSEL, 0, -1) ;
  362.                          return 0 ;
  363.  
  364.                               // Messages from Search menu
  365.  
  366.                     case IDM_FIND :
  367.                          SendMessage (hwndEdit, EM_GETSEL, NULL,
  368.                                                            (LPARAM) &iOffset) ;
  369.  
  370.                          hDlgModeless = PopFindFindDlg (hwnd) ;
  371.                          return 0 ;
  372.  
  373.                     case IDM_NEXT :
  374.                          SendMessage (hwndEdit, EM_GETSEL, NULL,
  375.                                                            (LPARAM) &iOffset) ;
  376.  
  377.                          if (PopFindValidFind ())
  378.                               PopFindNextText (hwndEdit, &iOffset) ;
  379.                          else
  380.                               hDlgModeless = PopFindFindDlg (hwnd) ;
  381.  
  382.                          return 0 ;
  383.  
  384.                     case IDM_REPLACE :
  385.                          SendMessage (hwndEdit, EM_GETSEL, NULL,
  386.                                                            (LPARAM) &iOffset) ;
  387.  
  388.                          hDlgModeless = PopFindReplaceDlg (hwnd) ;
  389.                          return 0 ;
  390.  
  391.                     case IDM_FONT :
  392.                          if (PopFontChooseFont (hwnd))
  393.                               PopFontSetFont (hwndEdit) ;
  394.  
  395.                          return 0 ;
  396.  
  397.                               // Messages from Help menu
  398.  
  399.                     case IDM_HELP :
  400.                          OkMessage (hwnd, "Help not yet implemented!", "\0") ;
  401.                          return 0 ;
  402.  
  403.                     case IDM_ABOUT :
  404.                          DialogBox (hInst, "AboutBox", hwnd, AboutDlgProc) ;
  405.                          return 0 ;
  406.                     }
  407.                break ;
  408.  
  409.           case WM_CLOSE :
  410.                if (!bNeedSave || IDCANCEL != AskAboutSave (hwnd, szTitleName))
  411.                     DestroyWindow (hwnd) ;
  412.  
  413.                return 0 ;
  414.  
  415.           case WM_QUERYENDSESSION :
  416.                if (!bNeedSave || IDCANCEL != AskAboutSave (hwnd, szTitleName))
  417.                     return 1 ;
  418.  
  419.                return 0 ;
  420.  
  421.           case WM_DESTROY :
  422.                PopFontDeinitialize () ;
  423.                PostQuitMessage (0) ;
  424.                return 0 ;
  425.  
  426.           default:
  427.                          // Process "Find-Replace" iMsgs
  428.  
  429.                if (iMsg == iMsgFindReplace)
  430.                     {
  431.                     pfr = (LPFINDREPLACE) lParam ;
  432.  
  433.                     if (pfr->Flags & FR_DIALOGTERM)
  434.                          hDlgModeless = NULL ;
  435.  
  436.                     if (pfr->Flags & FR_FINDNEXT)
  437.                          if (!PopFindFindText (hwndEdit, &iOffset, pfr))
  438.                               OkMessage (hwnd, "Text not found!", "\0") ;
  439.  
  440.                     if (pfr->Flags & FR_REPLACE ||
  441.                         pfr->Flags & FR_REPLACEALL)
  442.                          if (!PopFindReplaceText (hwndEdit, &iOffset, pfr))
  443.                               OkMessage (hwnd, "Text not found!", "\0") ;
  444.  
  445.                     if (pfr->Flags & FR_REPLACEALL)
  446.                          while (PopFindReplaceText (hwndEdit, &iOffset, pfr)) ;
  447.  
  448.                     return 0 ;
  449.                     }
  450.                break ;
  451.           }
  452.      return DefWindowProc (hwnd, iMsg, wParam, lParam) ;
  453.      }
  454.  
  455. BOOL CALLBACK AboutDlgProc (HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
  456.      {
  457.      switch (iMsg)
  458.           {
  459.           case WM_INITDIALOG :
  460.                return TRUE ;
  461.  
  462.           case WM_COMMAND :
  463.                switch (LOWORD (wParam))
  464.                     {
  465.                     case IDOK :
  466.                          EndDialog (hDlg, 0) ;
  467.                          return TRUE ;
  468.                     }
  469.                break ;
  470.           }
  471.      return FALSE ;
  472.      }
  473.